package com.example.administrator.autofittextview.Widget;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Build;
import android.text.Editable;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextWatcher;
import android.text.method.SingleLineTransformationMethod;
import android.text.method.TransformationMethod;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;
import com.example.administrator.autofittextview.R;

public class AutoFitTextView extends TextView  implements TextWatcher  ,View.OnLayoutChangeListener {
    private TextPaint paint;
    private int   maxLines;       //字符最大行数
    private int   minTextSize;   //最小字符字体大小
    private float maxTextSize;   //最大字符字体大小
    private float precision;     //精度
    private boolean sizeToFit;
    private static final boolean SPEW = true;
    private static final int DEFAULT_MIN_TEXT_SIZE = 8; //sp
    private static final float DEFAULT_PRECISION = 0.5f;
    private OnTextSizeChangeListener listener=null;

    public void init(Context context) {
        float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity; /// * 将px值转换为sp值，保证文字大小不变
        paint =new TextPaint();
        maxTextSize=getTextSize();                          // 默认最大字体大小
        maxLines=initMaxLines();                             //字符最大行数
        sizeToFit = true;
        minTextSize =(int)scaledDensity * DEFAULT_MIN_TEXT_SIZE;  //默认最小字体大小
        precision=DEFAULT_PRECISION;                        //精度
    }
    public AutoFitTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public AutoFitTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AutoFitTextView, defStyle, 0);
        sizeToFit = ta.getBoolean(R.styleable.AutoFitTextView_sizeToFit, sizeToFit);//决定在前面添加还是后面添加内容 true是后面添加内容（默认） false 前面添加内容
        minTextSize = ta.getDimensionPixelSize(R.styleable.AutoFitTextView_minTextSize,(int) minTextSize);  //得到默认字体大小
        precision = ta.getFloat(R.styleable.AutoFitTextView_precision, precision);               //得到精度
        ta.recycle();
        this.addTextChangedListener(this);
        this.addOnLayoutChangeListener(this);
    }
    public int initMaxLines() {
        int maxLines = -1; // No limit (Integer.MAX_VALUE also means no limit)
        TransformationMethod method = this.getTransformationMethod();
        if (method != null && method instanceof SingleLineTransformationMethod) { //判断textview  是否为单行显示
            maxLines = 1;
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // 2012.06	16	4.1	JELLY_BEAN	Jelly Bean	果冻豆
            maxLines = super.getMaxLines();
        }
        return maxLines;
    }
    private int getLineCount(CharSequence text, float size, float width, DisplayMetrics displayMetrics) {
        paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, size, displayMetrics));
        StaticLayout layout = new StaticLayout(text, paint, (int)width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
        return layout.getLineCount();
    }
    private float measureMoreSize(CharSequence text,float targetWidth, int maxLines, float low, float high, float precision, DisplayMetrics displayMetrics) {
        float mid = (low + high) / 2.0f;
        paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, mid, displayMetrics));
        StaticLayout layout =new StaticLayout(text, paint, (int)targetWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
        int lineCount = layout.getLineCount();
        if ((high - low) < precision) {
            return low;
        }
        if (lineCount > maxLines) {
            return measureMoreSize(text, targetWidth, maxLines, low, mid, precision, displayMetrics);
        }
        if (lineCount < maxLines) {
            return measureMoreSize(text, targetWidth, maxLines, mid, high, precision, displayMetrics);
        }
        return mid;
    }
    private void autoSize(float minTextSize, float maxTextSize, int maxLines, float precision) {
        float resultSize =maxTextSize;
        if (maxLines <= 0 || maxLines == Integer.MAX_VALUE) {
            return;
        }
        int targetWidth = this.getWidth() - this.getPaddingLeft() - this.getPaddingRight();
        if (targetWidth <= 0) {
            return;
        }
        //得到text  内容
        CharSequence text = this.getText();
        TransformationMethod method = this.getTransformationMethod();
        if (method != null) {
            text = method.getTransformation(text, this);
        }
        //得到r  资源
        Context context = this.getContext();
        Resources r = Resources.getSystem();
        if (context != null) {
            r = context.getResources();
        }

        DisplayMetrics displayMetrics=r.getDisplayMetrics();
        paint.set(this.getPaint());
        paint.setTextSize(maxTextSize);

        if(maxLines == 1 && paint.measureText(text, 0, text.length()) > targetWidth) {
             if(listener==null || !listener.onTextSizeChange())
                resultSize = measureOneSize(text, targetWidth, maxLines, 0, maxTextSize, precision, displayMetrics);
        }
        if(maxLines >1 && getLineCount(text, resultSize, targetWidth, displayMetrics) > maxLines) {
            resultSize = measureMoreSize(text, targetWidth, maxLines, 0, maxTextSize, precision, displayMetrics);
        }
        if (resultSize < minTextSize) {
            resultSize = minTextSize;
        }
        this.setTextSize(TypedValue.COMPLEX_UNIT_PX, resultSize);
    }
    private float measureOneSize(CharSequence text,float targetWidth, int maxLines, float low, float high, float precision, DisplayMetrics displayMetrics) {
        float mid = (low + high) / 2.0f;
        paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, mid, displayMetrics));
        float maxLineWidth = paint.measureText(text, 0, text.length());  //计算出字符集宽度
        if ((high - low) < precision) {
            return low;
        }
        if (maxLineWidth > targetWidth) {
            return measureOneSize(text,  targetWidth, maxLines, low, mid, precision, displayMetrics);
        }
        if (maxLineWidth < targetWidth) {
            return measureOneSize(text, targetWidth, maxLines, mid, high, precision, displayMetrics);
        }
        return mid;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        autoSize(minTextSize, maxTextSize, maxLines, precision);
    }

    @Override
    public void afterTextChanged(Editable s) {

    }
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        autoSize(minTextSize, maxTextSize, maxLines, precision);
    }
    public interface OnTextSizeChangeListener{
        public boolean onTextSizeChange();
    }
    public  void  setOnTextSizeChangeListener(OnTextSizeChangeListener listener){
        this.listener=listener;
    }
}